package com.fowo.api.shein.util;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import static javax.xml.crypto.dsig.SignatureMethod.HMAC_SHA256;
import static javax.xml.transform.OutputKeys.ENCODING;

public class ApiSignUtil {

    public static String getSign(String openKeyId,String urlPath,String secretKey,String timestamp){

        String signString = openKeyId + "&" + timestamp + "&" + urlPath;

        String randomKey = UUID.randomUUID().toString().substring(0, 5);
        String randomSecretKey = secretKey + randomKey;

        String hashValue = ApiSignUtil.hmacSha256(signString, randomSecretKey);
        String base64Value = ApiSignUtil.base64Encode(hashValue);
        String signature = randomKey + base64Value;
        return signature;
    }

    public static String hmacSha256(String message, String secret) {
        String hash = "";
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
            mac.init(secretKey);
            byte[] bytes = mac.doFinal(message.getBytes());
            hash = byteArrayToHexString(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return hash;
    }

    private static String byteArrayToHexString(byte[] b) {
        StringBuilder hs = new StringBuilder();
        String tmp;
        for (int n = 0; b != null && n < b.length; n++) {
            tmp = Integer.toHexString(b[n] & 0XFF);
            if (tmp.length() == 1) {
                hs.append('0');
            }
            hs.append(tmp);
        }
        return hs.toString().toLowerCase();
    }

    public static String base64Encode(String data) {
        String result = "";
        if (StringUtils.isNotBlank(data)) {
            result = new String(Base64.encodeBase64(data.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
        }
        return result;
    }

    public static String doPost(String url, Map<String, String> headers, String json) throws Exception {
        // 创建httpClient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();

        // 创建http对象
        HttpPost httpPost = new HttpPost(url);
        /**
         * setConnectTimeout：设置连接超时时间，单位毫秒。
         * setConnectionRequestTimeout：设置从connect Manager(连接池)获取Connection
         * 超时时间，单位毫秒。这个属性是新加的属性，因为目前版本是可以共享连接池的。
         * setSocketTimeout：请求获取数据的超时时间(即响应时间)，单位毫秒。 如果访问一个接口，多少时间内无法返回数据，就直接放弃此次调用。
         */
        RequestConfig requestConfig = RequestConfig.custom().build();
        httpPost.setConfig(requestConfig);
        // 封装请求头
        if (headers != null) {
            Set<Map.Entry<String, String>> entrySet = headers.entrySet();
            for (Map.Entry<String, String> entry : entrySet) {
                // 设置到请求头到HttpRequestBase对象中
                httpPost.setHeader(entry.getKey(), entry.getValue());
            }
        }

        // 封装请求参数
        if (json != null) {
            // 设置到请求的http对象中
            httpPost.setEntity(new StringEntity(json, ENCODING));
        }

        try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost);) {
            // 执行请求并获得响应结果
            return EntityUtils.toString(httpResponse.getEntity(), ENCODING);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
